 # -*- coding: utf-8 -*-
"""
Created on Fri Sep 17 10:29:29 2021
用 tf2 写一个从 任意态 态制备到 Bell 态的 DQN 算法
@author: Waikikilick
"""

import  os
os.environ['TF_CPP_MIN_LOG_LEVEL']='2' #设置 tf 的报警等级
import tensorflow as tf
import numpy as np
from tensorflow import keras
from tensorflow.keras import layers,optimizers,losses,initializers,Sequential,metrics,models
import copy 
from collections import deque
import random
from scipy.linalg import expm
from time import *

tf.random.set_seed(1)
np.random.seed(1)
random.seed (1)

class env(object):
    def  __init__(self, 
        dt = np.pi / 2,
        noise_a = 0,
        ): 
        self.action_space = np.array(  [[1,1],
                                        [1,2],
                                        [1,3],
                                        [1,4],
                                        [1,5],
                                        [2,1],
                                        [2,2],
                                        [2,3],
                                        [2,4],
                                        [2,5],
                                        [3,1],
                                        [3,2],
                                        [3,3],
                                        [3,4],
                                        [3,5],
                                        [4,1],
                                        [4,2],
                                        [4,3],
                                        [4,4],
                                        [4,5],
                                        [5,1],
                                        [5,2],
                                        [5,3],
                                        [5,4],
                                        [5,5]] )
        self.n_actions = len(self.action_space)
        self.n_features = 8 #描述状态所用的长度
        self.target_psi =  np.mat([[1], [0], [0], [1]], dtype=complex)/np.sqrt(2) #最终的目标态为 |0>,  np.array([1,0,0,0])
        self.h_1 = 1
        self.h_2 = 1
        self.I = np.matrix(np.identity(2, dtype=complex))
        self.s_x = np.mat([[0, 1], [1, 0]], dtype=complex)
        self.s_z = np.mat([[1, 0], [0, -1]], dtype=complex)
        self.dt = dt
        self.training_set, self.validation_set, self.testing_set = self.psi_set()
        self.noise_normal_1 = np.array(
                  [ 1.62434536e+00, -6.11756414e-01, -5.28171752e-01, -1.07296862e+00,
                    8.65407629e-01, -2.30153870e+00,  1.74481176e+00, -7.61206901e-01,
                    3.19039096e-01, -2.49370375e-01,  1.46210794e+00, -2.06014071e+00,
                   -3.22417204e-01, -3.84054355e-01,  1.13376944e+00, -1.09989127e+00,
                   -1.72428208e-01, -8.77858418e-01,  4.22137467e-02,  5.82815214e-01,
                   -1.10061918e+00,  1.14472371e+00,  9.01590721e-01,  5.02494339e-01,
                    9.00855949e-01, -6.83727859e-01, -1.22890226e-01, -9.35769434e-01,
                   -2.67888080e-01,  5.30355467e-01, -6.91660752e-01, -3.96753527e-01,
                   -6.87172700e-01, -8.45205641e-01, -6.71246131e-01, -1.26645989e-02,
                   -1.11731035e+00,  2.34415698e-01,  1.65980218e+00,  7.42044161e-01,
                   -1.91835552e-01, -8.87628964e-01, -7.47158294e-01,  1.69245460e+00,
                    5.08077548e-02, -6.36995647e-01,  1.90915485e-01,  2.10025514e+00])
        
        self.noise_normal_2 = np.array(
                   [-4.16757847e-01, -5.62668272e-02, -2.13619610e+00,  1.64027081e+00,
                    -1.79343559e+00, -8.41747366e-01,  5.02881417e-01, -1.24528809e+00,
                    -1.05795222e+00, -9.09007615e-01,  5.51454045e-01,  2.29220801e+00,
                     4.15393930e-02, -1.11792545e+00,  5.39058321e-01, -5.96159700e-01,
                    -1.91304965e-02,  1.17500122e+00, -7.47870949e-01,  9.02525097e-03,
                    -8.78107893e-01, -1.56434170e-01,  2.56570452e-01, -9.88779049e-01,
                    -3.38821966e-01, -2.36184031e-01, -6.37655012e-01, -1.18761229e+00,
                    -1.42121723e+00, -1.53495196e-01, -2.69056960e-01,  2.23136679e+00,
                    -2.43476758e+00,  1.12726505e-01,  3.70444537e-01,  1.35963386e+00,
                     5.01857207e-01, -8.44213704e-01,  9.76147160e-06,  5.42352572e-01,
                    -3.13508197e-01,  7.71011738e-01, -1.86809065e+00,  1.73118467e+00,
                     1.46767801e+00, -3.35677339e-01,  6.11340780e-01,  4.79705919e-02])
    
        
        self.noise_constant = np.ones(41)
        
    def psi_set(self):
        
        alpha_num = 4
        
        theta = [np.pi/8,np.pi/4,3*np.pi/8]
        theta_1 = theta
        theta_2 = theta
        theta_3 = theta
        
        alpha = np.linspace(0,np.pi*2,alpha_num,endpoint=False)
        alpha_1 = alpha
        alpha_2 = alpha
        alpha_3 = alpha
        alpha_4 = alpha
        
        psi_set = []#np.matrix([[0,0,0,0]],dtype=complex) #第一行用来占位，否则无法和其他行并在一起，在最后要注意去掉这一行
        for ii in range(3): #theta_1
            for jj in range(3): #theta_2
                for kk in range(3): #theta_3
                    for mm in range(alpha_num): #alpha_1
                        for nn in range(alpha_num): #alpha_2
                            for oo in range(alpha_num): #alpha_3
                                for pp in range(alpha_num): #alpha_4
                                    
                                    a_1_mo = np.cos(theta_1[ii])
                                    a_2_mo = np.sin(theta_1[ii])*np.cos(theta_2[jj])
                                    a_3_mo = np.sin(theta_1[ii])*np.sin(theta_2[jj])*np.cos(theta_3[kk])
                                    a_4_mo = np.sin(theta_1[ii])*np.sin(theta_2[jj])*np.sin(theta_3[kk])
                                    
                                    a_1_real = a_1_mo*np.cos(alpha_1[mm])
                                    a_1_imag = a_1_mo*np.sin(alpha_1[mm])
                                    a_2_real = a_2_mo*np.cos(alpha_2[nn])
                                    a_2_imag = a_2_mo*np.sin(alpha_2[nn])
                                    a_3_real = a_3_mo*np.cos(alpha_3[oo])
                                    a_3_imag = a_3_mo*np.sin(alpha_3[oo])
                                    a_4_real = a_4_mo*np.cos(alpha_4[pp])
                                    a_4_imag = a_4_mo*np.sin(alpha_4[pp])
                                    
                                    a_1_complex = a_1_real + a_1_imag*1j
                                    a_2_complex = a_2_real + a_2_imag*1j
                                    a_3_complex = a_3_real + a_3_imag*1j
                                    a_4_complex = a_4_real + a_4_imag*1j
                                    
                                    a_complex = np.mat([[ a_1_complex], [a_2_complex], [a_3_complex], [a_4_complex]])
                                    # psi_set = np.row_stack((psi_set,a_complex))
                                    psi_set.append(a_complex)
                                    
        # psi_set = np.array(np.delete(psi_set,0,axis=0)) # 删除矩阵的第一行
        random.shuffle(psi_set) #打乱顺序
    
        training_set = psi_set[0:256]
        validation_set = psi_set[256:512]
        # testing_set = psi_set[512:1536]
        testing_set = psi_set[512:]
        
        return training_set, validation_set, testing_set
        
    
    def reset(self, init_psi): # 在一个新的回合开始时，归位到开始选中的那个点上
        
        init_state = np.array(init_psi.real.tolist() + init_psi.imag.tolist()) # 实向量形式
        # np.array([1实，2实，1虚，2虚])
        return init_state
    
    
    def step(self, state, action, nstep):
        
        psi = np.mat((np.array([state[0:int(len(state) / 2)] + state[int(len(state) / 2):int(len(state))] * 1j]).T).squeeze(0))  # 从 实向量 变回 复矩阵 形式
        #matrix([[ 1实 + 1虚j],
        #        [ 2实 + 2虚j]])
        
        J_1, J_2 =  self.action_space[action,0], self.action_space[action,1]  # control field strength
        J_12 = J_1 * J_2 /2
        
        H =  (J_1*np.kron(self.s_z, self.I) + J_2*np.kron(self.I, self.s_z) + \
                        J_12/2*np.kron((self.s_z-self.I),(self.s_z-self.I)) + \
           self.h_1*np.kron(self.s_x,self.I) + self.h_2*np.kron(self.I,self.s_x))/2
        U = expm(-1j * H * self.dt) 
        psi = U * psi  # next state

        err = 10e-4
        fid = (np.abs(psi.H * self.target_psi) ** 2).item(0).real  
        rwd = fid
        
        done = (((1 - fid) < err) or nstep >= 20 * np.pi / self.dt)  

        #再将量子态的 psi 形式恢复到 state 形式。 # 因为网络输入不能为复数，否则无法用寻常基于梯度的算法进行反向传播
    
        state = np.array(psi.real.tolist() + psi.imag.tolist()) # 实向量形式

        return state, rwd, done, fid    
    
    def step_noise_J(self, state, action, nstep):
        
        psi = np.mat((np.array([state[0:int(len(state) / 2)] + state[int(len(state) / 2):int(len(state))] * 1j]).T).squeeze(0))  # 从 实向量 变回 复矩阵 形式      
        J_1, J_2 =  self.action_space[action,0], self.action_space[action,1]  # control field strength
        J_1 += self.noise_1[nstep]
        J_2 += self.noise_2[nstep]
        J_12 = J_1 * J_2 /2
        
        H =  (J_1*np.kron(self.s_z, self.I) + J_2*np.kron(self.I, self.s_z) + \
                        J_12/2*np.kron((self.s_z-self.I),(self.s_z-self.I)) + \
           self.h_1*np.kron(self.s_x,self.I) + self.h_2*np.kron(self.I,self.s_x))/2
        U = expm(-1j * H * self.dt) 
        psi = U * psi  # next state
        fid = (np.abs(psi.H * self.target_psi) ** 2).item(0).real      
        state = np.array(psi.real.tolist() + psi.imag.tolist()) # 实向量形式

        return state, fid    
    
    def step_noise_h(self, state, action, nstep):
        
        psi = np.mat((np.array([state[0:int(len(state) / 2)] + state[int(len(state) / 2):int(len(state))] * 1j]).T).squeeze(0))  # 从 实向量 变回 复矩阵 形式      
        J_1, J_2 =  self.action_space[action,0], self.action_space[action,1]  # control field strength
        J_12 = J_1 * J_2 /2
        h_1 = self.h_1 + self.noise_1[nstep] #加入噪声1
        h_2 = self.h_2 + self.noise_2[nstep] #加入噪声2
        
        H =  (J_1*np.kron(self.s_z, self.I) + J_2*np.kron(self.I, self.s_z) + \
                        J_12/2*np.kron((self.s_z-self.I),(self.s_z-self.I)) + \
           h_1*np.kron(self.s_x,self.I) + h_2*np.kron(self.I,self.s_x))/2
        U = expm(-1j * H * self.dt) 
        psi = U * psi  # next state
        fid = (np.abs(psi.H * self.target_psi) ** 2).item(0).real      
        state = np.array(psi.real.tolist() + psi.imag.tolist()) # 实向量形式

        return state, fid    

def relu(vector):
    for i in range(len(vector)):
        vector[i] = np.maximum(0,vector[i])
    return vector

def agent(x):
    out = np.mat(x).T * net[0].numpy() + net[1].numpy()
    out = relu(out)
    out = out * net[2].numpy() + net[3].numpy()
    out = relu(out)
    out = out * net[4].numpy() + net[5].numpy()
    out = relu(out)
    out = out * net[6].numpy() + net[7].numpy()
    out = relu(out)
    action = np.argmax(out)
    return action

def testing(): # 测试 测试集中的点 得到 保真度 分布
    print('\n测试中, 请稍等...')
    
    testing_set = env.testing_set
    fid_list = []
    
    for test_init_psi in testing_set:
        
        fid_max = 0
        observation = env.reset(test_init_psi)
        nstep = 0
        
        while True:
            action = agent(observation) 
            observation_, reward, done, fid = env.step(observation, action, nstep)  
            nstep += 1
            fid_max = max(fid_max, fid)
            observation = observation_
                
            if done:
                break
            
        fid_list.append(fid_max)
        
    return fid_list

def testing_noise_J_dynamic(noise_a): # 测试 测试集中的点 得到 保真度 分布
    print('\n测试 J 动态噪声中, 请稍等...')
    print('噪声振幅为：', noise_a)
    env.noise_1 = noise_a * env.noise_normal_1
    env.noise_2 = noise_a * env.noise_normal_2
    fid_noise_list = []
    
    for test_init_psi in testing_set:
        
        fid_max = 0
        observation = env.reset(test_init_psi)
        nstep = 0
        action_list = [] #用来保存本回合所采取的动作，用于噪声分析
        fid_list = [] #用来保存本回合中的保真度，选择最大保真度对应的步骤作为后面噪声环境中动作的终止步骤
        
        while True:
            action = agent(observation) 
            observation_, reward, done, fid = env.step(observation, action, nstep) 
            action_list.append(action)
            fid_list.append(fid)
            nstep += 1
            fid_max = max(fid_max, fid)
            observation = observation_
                
            if done:
                break
            
        max_index = fid_list.index(max(fid_list))
        action_list = action_list[0:max_index+1]
        
        observation = env.reset(test_init_psi)
        
        # 加入噪声
        nstep = 0
        for action in action_list:
            
            observation_, fid = env.step_noise_J(observation, action, nstep)
            observation = observation_
            nstep += 1
             #选择最后一步的保真度作为本回合的保真度
            
        fid_noise_list.append(fid) # 将最终保真度记录到矩阵中
            
    return fid_noise_list   

def testing_noise_J_static(noise_a): # 测试 测试集中的点 得到 保真度 分布
    print('\n测试 J 静态噪声中, 请稍等...')
    print('噪声振幅为：', noise_a)
    env.noise_1 = noise_a * env.noise_constant
    env.noise_2 = noise_a * env.noise_constant
    fid_noise_list = []
    
    for test_init_psi in testing_set:
        
        fid_max = 0
        observation = env.reset(test_init_psi)
        nstep = 0
        action_list = [] #用来保存本回合所采取的动作，用于噪声分析
        fid_list = [] #用来保存本回合中的保真度，选择最大保真度对应的步骤作为后面噪声环境中动作的终止步骤
        
        while True:
            action = agent(observation) 
            observation_, reward, done, fid = env.step(observation, action, nstep) 
            action_list.append(action)
            fid_list.append(fid)
            nstep += 1
            fid_max = max(fid_max, fid)
            observation = observation_
                
            if done:
                break
            
        max_index = fid_list.index(max(fid_list))
        action_list = action_list[0:max_index+1]
        
        observation = env.reset(test_init_psi)
        
        # 加入噪声
        nstep = 0
        for action in action_list:
            
            observation_, fid = env.step_noise_J(observation, action, nstep)
            observation = observation_
            nstep += 1
             #选择最后一步的保真度作为本回合的保真度
            
        fid_noise_list.append(fid) # 将最终保真度记录到矩阵中
            
    return fid_noise_list   

def testing_noise_h_dynamic(noise_a): # 测试 测试集中的点 得到 保真度 分布
    print('\n测试 h 动态噪声中, 请稍等...')
    print('噪声振幅为：', noise_a)
    env.noise_1 = noise_a * env.noise_normal_1
    env.noise_2 = noise_a * env.noise_normal_2
    fid_noise_list = []
    
    for test_init_psi in testing_set:
        
        fid_max = 0
        observation = env.reset(test_init_psi)
        nstep = 0
        action_list = [] #用来保存本回合所采取的动作，用于噪声分析
        fid_list = [] #用来保存本回合中的保真度，选择最大保真度对应的步骤作为后面噪声环境中动作的终止步骤
        
        while True:
            action = agent(observation) 
            observation_, reward, done, fid = env.step(observation, action, nstep) 
            action_list.append(action)
            fid_list.append(fid)
            nstep += 1
            fid_max = max(fid_max, fid)
            observation = observation_
                
            if done:
                break
            
        max_index = fid_list.index(max(fid_list))
        action_list = action_list[0:max_index+1]
        
        observation = env.reset(test_init_psi)
        
        # 加入噪声
        nstep = 0
        for action in action_list:
            
            observation_, fid = env.step_noise_h(observation, action, nstep)
            observation = observation_
            nstep += 1
             #选择最后一步的保真度作为本回合的保真度
            
        fid_noise_list.append(fid) # 将最终保真度记录到矩阵中
            
    return fid_noise_list  

def testing_noise_h_static(noise_a): # 测试 测试集中的点 得到 保真度 分布
    print('\n测试 h 静态噪声中, 请稍等...')
    print('噪声振幅为：', noise_a)
    env.noise_1 = noise_a * env.noise_constant
    env.noise_2 = noise_a * env.noise_constant
    fid_noise_list = []
    
    for test_init_psi in testing_set:
        
        fid_max = 0
        observation = env.reset(test_init_psi)
        nstep = 0
        action_list = [] #用来保存本回合所采取的动作，用于噪声分析
        fid_list = [] #用来保存本回合中的保真度，选择最大保真度对应的步骤作为后面噪声环境中动作的终止步骤
        
        while True:
            action = agent(observation) 
            observation_, reward, done, fid = env.step(observation, action, nstep) 
            action_list.append(action)
            fid_list.append(fid)
            nstep += 1
            fid_max = max(fid_max, fid)
            observation = observation_
                
            if done:
                break
            
        max_index = fid_list.index(max(fid_list))
        action_list = action_list[0:max_index+1]
        
        observation = env.reset(test_init_psi)
        
        # 加入噪声
        nstep = 0
        for action in action_list:
            
            observation_, fid = env.step_noise_h(observation, action, nstep)
            observation = observation_
            nstep += 1
             #选择最后一步的保真度作为本回合的保真度
            
        fid_noise_list.append(fid) # 将最终保真度记录到矩阵中
            
    return fid_noise_list           
    
if __name__ == "__main__":
    
    dt = np.pi/2
    
    env = env(dt = dt)
    testing_set = env.testing_set          

    network = keras.models.load_model('dqn_tf2_two_qubit_to_Bell_saved_model') #导入训练好的网络 
    net = network.trainable_variables
    
    # 测试 噪声 对 保真度 的影响
    
    fids_noise_J_Static_list = []
    fids_noise_h_Static_list = []
    fids_noise_J_Dynamic_list = []
    fids_noise_h_Dynamic_list = []
    
    start_time = time()    
    for noise_a in [-0.01, -0.009, -0.008, -0.007, -0.006, -0.005, -0.004, -0.003, -0.002, -0.001, 0, 0.001, 0.002, 0.003, 0.004, 0.005, 0.006, 0.007, 0.008, 0.009, 0.01]:
        test_noise_mean = np.mean(testing_noise_J_static(noise_a))
        end_time = time()
        print(' J 静态噪声下的平均保真度为：',test_noise_mean)
        print('所用时间为：', end_time - start_time)
        fids_noise_J_Static_list.append(test_noise_mean)
     
    start_time = time()  
    for noise_a in [-0.01, -0.009, -0.008, -0.007, -0.006, -0.005, -0.004, -0.003, -0.002, -0.001, 0, 0.001, 0.002, 0.003, 0.004, 0.005, 0.006, 0.007, 0.008, 0.009, 0.01]:
        test_noise_mean = np.mean(testing_noise_h_static(noise_a))
        end_time = time()
        print(' h 静态噪声下的平均保真度为：',test_noise_mean)
        print('所用时间为：', end_time - start_time)
        fids_noise_h_Static_list.append(test_noise_mean)
        
    start_time = time()  
    for noise_a in [0, 0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07, 0.08, 0.09, 0.1]:
        test_noise_mean = np.mean(testing_noise_J_dynamic(noise_a))
        end_time = time()
        print(' J 动态噪声下的平均保真度为：',test_noise_mean)
        print('所用时间为：', end_time - start_time)
        fids_noise_J_Dynamic_list.append(test_noise_mean) 
    
    start_time = time()  
    for noise_a in [0, 0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07, 0.08, 0.09, 0.1]:
        test_noise_mean = np.mean(testing_noise_h_dynamic(noise_a))
        end_time = time()
        print(' h 动态噪声下的平均保真度为：',test_noise_mean)
        print('所用时间为：', end_time - start_time)
        fids_noise_h_Dynamic_list.append(test_noise_mean) 
    
    
    print('fids_noise_J_Static_list', fids_noise_J_Static_list)
    print('fids_noise_h_Static_list', fids_noise_h_Static_list)
    
    print('fids_noise_J_Dynamic_list', fids_noise_J_Dynamic_list)
    print('fids_noise_h_Dynamic_list', fids_noise_h_Dynamic_list)
    
 # 1024 个测试点结果 ：  
    # fids_noise_J_Static_list [0.955440389826011, 0.9580225304625387, 0.960363042244727, 0.9624544973356016, 0.9642896825972432, 0.9658616279949706, 0.967163635387029, 0.9681893075682393, 0.9689325774274999, 0.969387737070878, 0.969549466754459, 0.9694128634645843, 0.9689734689771943, 0.9682272972235801, 0.9671708607854155, 0.9658011963401781, 0.9641158888760841, 0.9621130944958494, 0.959791561630113, 0.9571506504836098, 0.9541903505418855]
    # fids_noise_h_Static_list [0.9689329385447929, 0.9691473178758077, 0.9693275674970633, 0.9694737475013158, 0.969585924544241, 0.9696641717751218, 0.9697085687674101, 0.9697192014488993, 0.9696961620319156, 0.9696395489432891, 0.969549466754459, 0.9694260261116597, 0.9692693436661647, 0.9690795420048741, 0.9688567495810897, 0.968601100645649, 0.9683127351784124, 0.9679917988202859, 0.9676384428054977, 0.9672528238946019, 0.966835104307906]
    # fids_noise_J_Dynamic_list [0.969549466754459, 0.9660144792597876, 0.9561552232704018, 0.9404651188807958, 0.9196033350691976, 0.8943495634751534, 0.8655550537874102, 0.8340941322164802, 0.8008200009293519, 0.7665278342564219, 0.7319271599850194]
    # fids_noise_h_Dynamic_list [0.969549466754459, 0.9691763947168269, 0.9677857761636206, 0.9654012553450695, 0.9620504641586368, 0.9577646375190945, 0.9525782171593458, 0.9465284497843287, 0.939654985089735, 0.9319994786821588, 0.9236052044159028]
 
 # 所有测试点结果：
    
    # fids_noise_J_Static_list [0.955459323191412, 0.9580893067214542, 0.9604716129882622, 0.96259896226556, 0.9644643269982953, 0.9660609596208175, 0.9673824204889476, 0.9684226057915448, 0.9691757753000032, 0.9696365798073565, 0.9698000881025619, 0.9696618133204651, 0.9692177385035677, 0.968464341208863, 0.9673986169901942, 0.9660181015864906, 0.9643208916459792, 0.962305663818442, 0.9599716920509513, 0.9573188629266829, 0.9543476888930676]
                                # 0.95545932 0.95808931 0.96047161 0.96259896 0.96446433 0.96606096 0.96738242 0.96842261 0.96917578 0.96963658 0.96980009 0.96966181 0.96921774 0.96846434 0.96739862 0.9660181  0.96432089 0.96230566 0.95997169 0.95731886 0.95434769
 
    # fids_noise_h_Static_list [0.9690391874220577, 0.9692683311406605, 0.9694633165590002, 0.969624184410797, 0.9697509835909633, 0.9698437710996417, 0.9699026119825505, 0.9699275792673723, 0.969918753896572, 0.9698762246564187, 0.9698000881025619, 0.9696904484821285, 0.9695474176523297, 0.9693711149958963, 0.9691616673332085, 0.9689192088313365, 0.9686438809100253, 0.9683358321448575, 0.9679952181673689, 0.9676222015626447, 0.9672169517641711]
                                # 0.96903919 0.96926833 0.96946332 0.96962418 0.96975098 0.96984377 0.96990261 0.96992758 0.96991875 0.96987622 0.96980009 0.96969045 0.96954742 0.96937111 0.96916167 0.96891921 0.96864388 0.96833583 0.96799522 0.9676222  0.96721695

    # fids_noise_J_Dynamic_list [0.9698000881025619, 0.9666125881985923, 0.9572416093590838, 0.9420995759285995, 0.9217531913258261, 0.8968888513919164, 0.8682742094844172, 0.8367188951124033, 0.8030371642077057, 0.7680147954825602, 0.7323819126329902]
                                # 0.96980009 0.96661259 0.95724161 0.94209958 0.92175319 0.89688885 0.86827421 0.8367189  0.80303716 0.7680148  0.73238191

    # fids_noise_h_Dynamic_list [0.9698000881025619, 0.9694408493470732, 0.9680748364142215, 0.9657258005833456, 0.9624213488979472, 0.9581925723370871, 0.9530736656550439, 0.9471015441674819, 0.9403154623068588, 0.9327566382708525, 0.924467888562169]
                                # 0.96980009 0.96944085 0.96807484 0.9657258  0.96242135 0.95819257 0.95307367 0.94710154 0.94031546 0.93275664 0.92446789

